package com.jacen.etl.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

public class BeanUtils
{
  public static Object getProperty(Object bean, String name){
    try{
      if (bean == null) throw new Exception("实体对象不能为null");
      if ((name == null) || (name.trim().length() == 0)) throw new Exception("属性名不能为空");
      if (!hasProperty(bean.getClass(), name)) throw new Exception("无该属性：" + name);

      String methodName = getGetMethodName(bean.getClass(), name);
      Method method = bean.getClass().getMethod(methodName, new Class[0]);
      return method.invoke(bean, new Object[0]); } 
    catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public static Class<?> getPropertyType(Class<?> clazz, String name){
    try{
      if (clazz == null) throw new Exception("clazz不能为null");
      if ((name == null) || (name.trim().length() == 0)) throw new Exception("属性名不能为空");

      Field field = clazz.getDeclaredField(name);
      return field.getType(); 
    }catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public static boolean hasProperty(Class<?> clazz, String name){
    try{
      if (clazz == null) throw new Exception("Class不能为null");
      if ((name == null) || (name.trim().length() == 0)) throw new Exception("属性名不能为空");

      String methodName = getGetMethodName(clazz, name);
      clazz.getMethod(methodName, new Class[0]);
      methodName = getSetMethodName(clazz, name);
      clazz.getMethod(methodName, new Class[] { clazz.getDeclaredField(name).getType() });
      return true; 
    }catch (Exception e) {
      return false;
    }
  }

  public static void setProperty(Object bean, String name, Object value){
    try{
      if (bean == null) throw new Exception("实体对象不能为null");
      if ((name == null) || (name.trim().length() == 0)) throw new Exception("属性名不能为空");
      if (!hasProperty(bean.getClass(), name)) throw new Exception("无该属性：" + name);

      String methodName = getSetMethodName(bean.getClass(), name);
      Method method = bean.getClass().getMethod(methodName, new Class[] { bean.getClass().getDeclaredField(name).getType() });
      method.invoke(bean, new Object[] { value });
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public static void populate(Object bean, Map<String, Object> properties){
    if (bean == null) throw new RuntimeException("实体对象不能为null");
    if (properties == null) throw new RuntimeException("Map对象不能为null");

    Iterator<Entry<String,Object>> iter = properties.entrySet().iterator();
    while (iter.hasNext()) {
      Map.Entry<String,Object> entry = iter.next();
      setProperty(bean, (String)entry.getKey(), entry.getValue());
    }
  }

  public static void copyProperties(Object src, Object dest){
    Map<String, Object> map = describe(src);
    populate(dest, map);
  }

  public static Map<String, Object> describe(Object bean){
    if (bean == null) throw new RuntimeException("实体对象不能为null");

    Map<String, Object> map = new HashMap<String, Object>();
    Field[] fields = bean.getClass().getDeclaredFields();
    for (Field field : fields) {
      if (hasProperty(bean.getClass(), field.getName()))
        map.put(field.getName(), getProperty(bean, field.getName()));
    }
    return map;
  }

  public static Map<String, Class<?>> describeType(Class<?> clazz){
    Map<String, Class<?>> map = new HashMap<String, Class<?>>();
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
      if (hasProperty(clazz, field.getName()))
        map.put(field.getName(), field.getType());
    }
    return map;
  }

  public static String getGetMethodName(Class<?> clazz, String name){
    if (clazz == null) throw new RuntimeException("Class对象不能为null");
    if ((name == null) || (name.trim().length() == 0)) throw new RuntimeException("属性名不能为空");
    try
    {
      Field field = clazz.getDeclaredField(name);
      String fieldName = field.getName();
      String methodName = BeanUtils.normalize(fieldName);
      if ((field.getType().equals(Boolean.TYPE)) || (field.getType().equals(Boolean.class)))
        methodName = "is" + methodName;
      else
        methodName = "get" + methodName;
      return methodName;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public static String getSetMethodName(Class<?> clazz, String name){
    if (clazz == null) throw new RuntimeException("Class对象不能为null");
    if ((name == null) || (name.trim().length() == 0)) throw new RuntimeException("属性名不能为空");
    try{
      Field field = clazz.getDeclaredField(name);
      String fieldName = field.getName();
      String methodName = BeanUtils.normalize(fieldName);
      methodName = "set" + methodName;
      return methodName; 
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
  
  private static String normalize(String str){
    if (str == null) return null;
    if (str.trim().length() == 0) return str;

    StringBuilder sb = new StringBuilder();
    sb.append(Character.toUpperCase(str.charAt(0)));
    sb.append(str.substring(1));
    return sb.toString();
  }
  
  public static String createId32(){
    UUID guid = UUID.randomUUID();
    return guid.toString().replace("-", "");
  }
}